package com.atguigu.tingshu.search.service.impl;

import com.atguigu.tingshu.album.client.AlbumInfoFeignClient;
import com.atguigu.tingshu.album.client.CategoryFeignClient;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.BaseCategoryView;
import com.atguigu.tingshu.model.search.AlbumInfoIndex;
import com.atguigu.tingshu.model.search.AttributeValueIndex;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.search.repository.AlbumIndexRepository;
import com.atguigu.tingshu.search.service.SearchService;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.AlbumAttributeValueVo;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;


@Slf4j
@Service
@SuppressWarnings({"all"})
public class SearchServiceImpl implements SearchService {


    @Autowired
    private AlbumInfoFeignClient albumInfoFeignClient;
    @Autowired
    ThreadPoolExecutor threadPoolExecutor;
    @Autowired
    CategoryFeignClient categoryFeignClient;

    @Autowired
    UserInfoFeignClient userInfoFeignClient;

    @Autowired
    AlbumIndexRepository albumIndexRepository;


    @Override
    public void upperAlbum(Long albumId) {
        //本质就是将数据从各个表中查询，然后给AlbumInfoIndex中
        AlbumInfoIndex albumInfoIndex = new AlbumInfoIndex();
        //直接优化为多线程查询并封装
        CompletableFuture<AlbumInfo> albumInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //远程调用  根据专辑id获取专辑结果集
            Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfo(albumId);
            //判断是否为空
            Assert.notNull(albumInfoResult.getData(), "专辑不存在！");
            //获取结果集数据
            AlbumInfo albumInfo = albumInfoResult.getData();
            //判断是否为空
            Assert.notNull(albumInfo, "专辑不存在！");
            //属性复制
            BeanUtils.copyProperties(albumInfo, albumInfoIndex);
            List<AlbumAttributeValue> albumAttributeValueVoList = albumInfo.getAlbumAttributeValueVoList();
            if (!CollectionUtils.isEmpty(albumAttributeValueVoList)) {
                List<AttributeValueIndex> attributeValueIndexList = albumAttributeValueVoList.stream().map(albumAttributeValue -> {
                    AttributeValueIndex attributeValueIndex = new AttributeValueIndex();
                    attributeValueIndex.setAttributeId(albumAttributeValue.getAttributeId());
                    attributeValueIndex.setValueId(albumAttributeValue.getValueId());
                    return attributeValueIndex;
                }).collect(Collectors.toList());
                //赋值属性值
                albumInfoIndex.setAttributeValueIndexList(attributeValueIndexList);
            }
            return albumInfo;
        }, threadPoolExecutor).exceptionally(throwable -> {
            log.error("远程调用失败：{}", throwable.getMessage());
            return null;
        });

        //赋值三级分类id
        CompletableFuture<Integer> cateGoryCompletableFuture = albumInfoCompletableFuture.thenApplyAsync(albumInfo -> {
            Long category3Id = albumInfo.getCategory3Id();
            Result<BaseCategoryView> baseCategoryView = categoryFeignClient.getCategoryView(category3Id);
            Assert.notNull(baseCategoryView, "分类不存在！");
            BaseCategoryView baseCategoryViewData = baseCategoryView.getData();
            Assert.notNull(baseCategoryViewData, "分类不存在！");
            albumInfoIndex.setCategory1Id(baseCategoryViewData.getCategory1Id());
            albumInfoIndex.setCategory2Id(baseCategoryViewData.getCategory2Id());

            return 1;

        }, threadPoolExecutor).exceptionally(throwable -> {
            log.error("远程调用失败：{}", throwable.getMessage());
            return 0;
        });

        //赋值作者信息
        CompletableFuture<Integer> userInfoCompletableFuture = albumInfoCompletableFuture.thenApplyAsync(albumInfo ->
        {
            Result<UserInfoVo> userInfoResult = userInfoFeignClient.getUserInfoVo(albumInfo.getUserId());
            Assert.notNull(userInfoResult);
            UserInfoVo data = userInfoResult.getData();
            Assert.notNull(data);
            albumInfoIndex.setAlbumIntro(data.getNickname());
            return 1;
        }, threadPoolExecutor).exceptionally(throwable -> {
            log.error("获取作者信息失败：{}", throwable.getMessage());
            return 0;
        });

        //赋值统计数据
        CompletableFuture<Integer> albumStatVoCompletableFuture = albumInfoCompletableFuture.thenApplyAsync(albumInfo -> {
            Result<AlbumStatVo> albumStat = albumInfoFeignClient.getAlbumStat(albumInfo.getId());
            Assert.notNull(albumStat);
            AlbumStatVo albumStatVo = albumStat.getData();
            Assert.notNull(albumStatVo);

            albumInfoIndex.setBuyStatNum(albumStatVo.getBuyStatNum());
            albumInfoIndex.setCommentStatNum(albumStatVo.getCommentStatNum());
            albumInfoIndex.setPlayStatNum(albumStatVo.getPlayStatNum());
            albumInfoIndex.setSubscribeStatNum(albumStatVo.getSubscribeStatNum());
            return 1;
        }, threadPoolExecutor).exceptionally(throwable -> {
            log.error("查询专辑统计数据失败：{}", throwable.getMessage());
            return 0;
        });
        albumInfoIndex.setHotScore(new Random().nextDouble(10000));


        try {
            if (null == albumInfoCompletableFuture.get() || 0 == cateGoryCompletableFuture.get() || 0 == userInfoCompletableFuture.get())
                return;
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
        //多任务组合
        CompletableFuture.allOf(
                albumInfoCompletableFuture,
                cateGoryCompletableFuture,
                userInfoCompletableFuture,
                albumStatVoCompletableFuture
        ).join();

        albumIndexRepository.save(albumInfoIndex);
    }

    @Override
    public void lowerAlbum(Long albumId) {
        albumIndexRepository.deleteById(albumId);
    }
}
